package com.example.webmodule.listener;

import com.alibaba.fastjson2.JSON;
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.webmodule.model.ServiceInterface;
import com.example.webmodule.service.ServiceInterfaceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.context.ApplicationEvent;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @ClassName EY-AbstractUpdateTempalte
 * @Description com.example.webmodule.listener
 * @Author menyj
 * @Date 2025/3/25
 **/
@Slf4j
public abstract class AbstractUpdateTemplate {

    private ServiceInterfaceService serviceInterfaceService;
    public AbstractUpdateTemplate(ServiceInterfaceService serviceInterfaceService) {
        this.serviceInterfaceService = serviceInterfaceService;
    }
    public void update(String serviceId, ApplicationEvent event) {

        List<ServiceInterface> beforeUpdateList = getUpdateBeforeList(serviceId);

        // 如果 服务 信息不存在，将服务及接口保存
        if (CollectionUtils.isEmpty(beforeUpdateList)) {
            List<ServiceInterface> needUpdateList = getNeedUpdateList(event);
            serviceInterfaceService.saveOrUpdateBatch(needUpdateList);
        }
        else {
            // 通过数据库中已有的数据，对比nacos通知的数据
            Map<String, Set<String>> pathMethodMap = beforeUpdateList.stream()
                    .collect(Collectors.groupingBy(
                            ServiceInterface::getPath,
                            Collectors.mapping(ServiceInterface::getMethod, Collectors.toSet())
                    ));
//            log.info("pathMethodMap = {}", JSON.toJSONString(pathMethodMap));

            List<ServiceInterface> insertList = Lists.newArrayList();
            List<ServiceInterface> updateList = Lists.newArrayList();

            List<ServiceInterface> allNoticeServiceInterfaceList = getNeedUpdateList(event);

            if (CollectionUtils.isEmpty(allNoticeServiceInterfaceList)) {
                // 服务下线
                Wrapper wrapper = Wrappers.lambdaUpdate(ServiceInterface.class).set(ServiceInterface::getDeleteFlag, 1)
                                .eq(ServiceInterface::getServiceId, serviceId);
                serviceInterfaceService.update(wrapper);
            }
            else {
                for (ServiceInterface serviceInterface: allNoticeServiceInterfaceList) {
                    // 如果 扫描 path + method 不存在,将数据插入
                    if (!(pathMethodMap.containsKey(serviceInterface.getPath())
                            && pathMethodMap.get(serviceInterface.getPath()).contains(serviceInterface.getMethod()))) {
                        insertList.add(serviceInterface);
                    }
                    else {
                        updateList.add(serviceInterface);
                    }
                }

                if (CollectionUtils.isNotEmpty(insertList)) {
                    log.info("有新数据被发现");
                    serviceInterfaceService.saveOrUpdateBatch(insertList);
                }

                if (CollectionUtils.isNotEmpty(updateList)) {
                    // 如果存在的将 deleteFlag 标记为0
                    updateList.forEach(si -> {
                        si.setDeleteFlag(0);
                        LambdaUpdateWrapper<ServiceInterface> lambdaUpdateWrapper = Wrappers.lambdaUpdate();
                        lambdaUpdateWrapper.set(ServiceInterface::getDeleteFlag, 0)
                                .eq(ServiceInterface::getServiceId, si.getServiceId())
                                .eq(ServiceInterface::getPath, si.getPath())
                                .eq(ServiceInterface::getMethod, si.getMethod());
                        serviceInterfaceService.update(lambdaUpdateWrapper);
                    });
                }

                // 反向 查找 在数据库中 的数据， 查到的数据 deleteFlag 标记 1
                LambdaQueryWrapper<ServiceInterface>  wrapper = Wrappers.lambdaQuery(ServiceInterface.class)
                        .eq(ServiceInterface::getServiceId, serviceId);
                for (ServiceInterface serviceInterface : allNoticeServiceInterfaceList) {
                    wrapper.or(w-> w.eq(ServiceInterface::getServiceId, serviceInterface.getServiceId())
                            .eq(ServiceInterface::getPath, serviceInterface.getPath())
                            .eq(ServiceInterface::getMethod, serviceInterface.getMethod()));
                }
                // 获取更新后的数据
                List<ServiceInterface> updatedList = serviceInterfaceService.list(wrapper);

                // 找出 beforeUpdateList 中的对象中 path 和 method 字段不存在于 updatedList 中的数据
                Set<String> updatedPathMethodSet = updatedList.stream()
                        .map(si -> si.getPath() + "#" + si.getMethod())
                        .collect(Collectors.toSet());

                List<ServiceInterface> toDeleteList = beforeUpdateList.stream()
                        .filter(si -> !updatedPathMethodSet.contains(si.getPath() + "#" + si.getMethod()))
                        .peek(si -> si.setDeleteFlag(1))
                        .collect(Collectors.toList());

                log.info("接口已经不存在的数据 {}", JSON.toJSONString(toDeleteList));
                serviceInterfaceService.saveOrUpdateBatch(toDeleteList);
            }
        }
    }

    /**
     * 更新前的数据
     * @return
     */
    public abstract List<ServiceInterface> getUpdateBeforeList(String serviceId);

    public abstract List<ServiceInterface> getNeedUpdateList(ApplicationEvent event);
}
